/*
 * @Author: Clark
 * @Email: haixuanwoTxh@gmail.com
 * @Date: 2023-01-28 17:45:19
 * @LastEditors: Clark
 * @LastEditTime: 2023-01-28 17:56:51
 * @Description: file content
 */
#include "apue.h"
#include <pthread.h>
#include <syslog.h>

sigset_t mask;

extern int already_running(void);

void reread(void)
{
    // ...
}

void *thr_fn(void *arg)
{
    int err, signo;

    while (1)
    {
        err = sigwait(&mask, &signo);
        if (0 != err)
        {
            syslog(LOG_ERR, "sigwait failed");
            exit(1);
        }

        switch (signo)
        {
            case SIGHUP:
            {
                syslog(LOG_INFO, "Re-reading configuration file");
                reread();
                break;
            }
            case SIGTERM:
            {
                syslog(LOG_INFO, "got SIGTERM; exiting");
                exit(0);
            }
            default:
            {
                syslog(LOG_INFO, "unexpected signal %d\n", signo);
            }
        }
    }

    return NULL;
}

int main(int argc, char *argv[])
{
    int err;
    pthread_t tid;
    char *cmd;
    struct sigaction sa;

    if ((cmd = strrchr(argv[0], '/')) == NULL)
    {
        cmd = argv[0];
    }
    else
    {
        cmd++;
    }

    // Become a daemon
    daemonize(cmd);

    // Make sure only one copy of the daemon is running
    if (already_running())
    {
        syslog(LOG_ERR, "daemon already running");
        exit(1);
    }

    // Restore SIGHUP default and block all signals
    sa.sa_handler = SIG_DFL;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if (sigaction(SIGHUP, &sa, NULL) < 0)
    {
        err_quit("%s: can't restore SIGHUP default");
    }

    sigfillset(&mask);
    if ((err = pthread_sigmask(SIG_BLOCK, &mask, NULL)) != 0)
    {
        err_exit(err, "SIGHUP_BLOCK error");
    }

    // create a thread to handle SIGHUP and SIGTERM
    err = pthread_create(&tid, NULL, thr_fn, NULL);
    if (0 != err)
    {
        err_exit(err, "can't create thread");
    }

    // Process with the reset of the daemon
    // ...
    exit(0);
}
